#! /usr/bin/env python

import os
import re
import shutil
import markitdown
from datetime import date
import sys

from rich import print as rprint
from openpyxl import Workbook
from datetime import datetime
from pathlib import Path

sys.path.append(os.path.join(os.path.dirname(__file__), "../lib"))

from inner_util import prepare_dir, get_files

SRC_DIR = sys.argv[1]
DIST_DIR = "dist"


def remove_whitespace_except_newlines(text):
    # 使用正则表达式替换除换行符以外的空白字符
    # \s 匹配所有空白字符，包括空格、制表符等
    # [^\S\n] 匹配所有非换行符的空白字符
    cleaned_text = re.sub(r"[^\S\n]+", "", text)
    return cleaned_text


def remove_whitespace(text):
    # 使用正则表达式替换除换行符以外的空白字符
    # \s 匹配所有空白字符，包括空格、制表符等
    # [^\S\n] 匹配所有非换行符的空白字符
    cleaned_text = re.sub(r"[^\S]+", "", text)
    return cleaned_text


def find_first_date(text):
    last_mat = ""
    mat = re.search(r"(\d{4})年(\d{1,2})月(\d{1,2})日", text)
    if mat:
        last_mat = mat.groups()
        y, m, d = last_mat
        meeting_date = date(year=int(y), month=int(m), day=int(d))
        return meeting_date.strftime("%Y.%m.%d")
    return last_mat


def get_index_num(rows: list, reg_exp: re.Pattern) -> int:
    index = -1
    for i, row in enumerate(rows):
        if reg_exp.match(row.strip()):
            index = i
            break
    return index


def parse_lines(rows):
    doc = {
        "title": "",
        "code": "",
        "send_by": "",
        "send_to": "",
        "send_date": "",
        "first_date": "",
    }
    # Line by line processing
    reg_code = re.compile(r"\S+〔\d{4}〕\d+号")
    reg_title = re.compile(r"\S+[请示|函|通知|报告|意见|批复]$")
    reg_send_to = re.compile(r"\S+[:：]$")
    reg_send_date = re.compile(r"^\d{4}年\d{1,}月\d{1,}日$")
    code_row = get_index_num(rows, reg_code)
    send_to_end_row = get_index_num(rows, reg_send_to)
    title_end_row = get_index_num(rows, reg_title)
    send_date_row = get_index_num(rows, reg_send_date)
    if code_row != -1:
        reg_code_match = re.compile(r"(\S+〔\d{4}〕\d+号)")
        code_mat = reg_code_match.search(rows[code_row])
        if code_mat:
            doc["code"] = code_mat.group(1)
    if title_end_row != -1 and send_to_end_row != -1:
        doc["send_to"] = "".join(rows[title_end_row + 1 : send_to_end_row + 1]).replace(
            "[:：]", ""
        )
        doc["title"] = "".join(rows[code_row + 1 : title_end_row + 1])
    if send_date_row != -1:
        doc["send_by"] = rows[send_date_row - 1].strip()
        doc["send_date"] = datetime.strptime(
            rows[send_date_row], "%Y年%m月%d日"
        ).strftime("%Y-%m-%d")
    if doc["title"] == "":
        doc["title"] = "".join(rows)
    return doc


def parse_string(text):
    doc = {
        "title": "",
        "code": "",
        "send_by": "",
        "send_to": "",
        "send_date": "",
        "first_date": "",
    }
    # No line splitting processing
    reg_all = re.compile(
        r"((\S+)文件)*(\S+〔\d{4}〕\d+号)*(\S*的(请示|函|通知|报告|意见|批复))([^\s:：]+)[:：]"
    )
    matches = reg_all.search(text)
    if matches:
        doc["send_by"] = matches.group(2) if matches.group(2) else ""
        doc["code"] = matches.group(3) if matches.group(3) else ""
        doc["title"] = matches.group(4) if matches.group(4) else ""
        doc["send_to"] = matches.group(6) if matches.group(6) else ""
    else:
        doc["title"] = text
    if doc["send_by"] == "":
        doc["send_by"] = doc["title"].split("关于")[0]
    return doc


def log_err(err):
    with open("err.log", "a+", encoding="utf-8") as f:
        f.write(err)


def write_file(file_path, content):
    with open(f"dist/{file_path}.txt", "w", encoding="utf-8") as f:
        f.write(content)


def report(docs):
    print("Report")
    wb = Workbook()
    ws = wb.active
    # 序号	培训时间	培训施教机构	培训内容	培训类别	培训方式	学时	备注

    ws.append(
        [
            "序号",
            "培训时间",
            "培训施教机构",
            "培训内容",
            "培训类别",
            "培训方式",
            "学时",
            "备注",
        ]
    )

    for d in docs:
        ws.append(["", d["first_date"], d["send_by"], d["title"], "", "", "", ""])

    wb.save("dist.xlsx")


class DateDoc:
    def __init__(self, file_path):
        self.file_path = file_path

    def _convert(self):
        md = markitdown.MarkItDown()
        try:
            res = md.convert(self.file_path)
            return res.text_content
        except Exception as e:
            print("Error", e)
            # log_err(f"ERROR {self.file_path} 有问题")
            # log_err(e)
            raise e

    def _copy_to(self, first_date=""):
        src_name = Path(self.file_path).name
        new_name = f"{first_date}-{src_name}" if first_date != "" else src_name
        target_file_path = Path(DIST_DIR, new_name)
        shutil.copy(self.file_path, target_file_path)

    def parse(self):
        """解析内容，检查第一个日期，检查文档元数据"""
        # 这个函数是对外的
        # 如果解析出内容，解析出第一个日期则改名称移动文件
        # 如果解析不出内容，原名称移动文件
        # 解析的内容
        text = self._convert()

        # 如果没内容，原名称复制文件
        if text is None or text == "":
            self._copy_to()
            return None

        # 去除所有空白字符，检测第一个日期，因为有可能会被写在两行上，所以要去除空白
        no_white_text = remove_whitespace(text)
        first_date = find_first_date(no_white_text)

        # Split by line, clean up whitespace
        rows = []
        for v in text.split("\n"):
            if v.strip() != "":
                v = re.sub(r"[\s\t]", "", v)
                v = re.sub(r"[\(（]", "（", v)
                v = re.sub(r"[\)）]", "）", v)
                rows.append(v)

        if len(rows) > 1:
            doc = parse_lines(rows)
        else:
            doc = parse_string(rows[0])

        doc["first_date"] = first_date

        rprint("dd", doc)
        self._copy_to(first_date)
        return doc


def main():
    print("Start")

    prepare_dir("dist")

    valid_exts = [".docx", ".pdf", ".doc", ".wps"]
    all_files = get_files(SRC_DIR, valid_exts, recursive=True)

    # print("All files", all_files)
    docs = []

    for f in all_files:
        date_doc = DateDoc(f)
        obj = date_doc.parse()
        if obj is not None and obj["first_date"] != "":
            docs.append(obj)

    docs.sort(key=lambda x: x["first_date"])
    report(docs)

    # write_file(target_file, res.text_content)


if __name__ == "__main__":
    main()
